/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Sent_Ip.c                                                                                  *
 * \brief    AUTOSAR 4.3.1 MCAL sent low level Driver                                                   *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2024/10/22     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "Sent_IpRegs.h"
#include "Sent_IpFault.h"
#include "Sent_Ip.h"
#include "stddef.h"

#ifdef CFG_PLATFORM_MCAL
#include "RegHelper.h"
#define SENT_START_SEC_CODE
#include "Sent_MemMap.h"
#elif CFG_PLATFORM_SSDK
#else
#error "Undefined macros CFG_PLATFORM_MCAL or CFG_PLATFORM_SSDK"
#endif /** #ifdef CFG_PLATFORM_MCAL */

/********************************************************************************************************
 *                                  Private Function Declarations                                       *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief Configure the sent timestamp feature to initialise the interface.
 *
 * \verbatim
 * Syntax             : void Sent_Ip_TimeStampInit(uint32_t base,
 *                          uint32_t preDiv)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - Sent base address
 *                      preDiv - Sent time stamp divider
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure the sent timestamp feature to initialise the interface.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_TimeStampInit(uint32_t base, uint32_t preDiv)
{
    uint32_t val;

    val = FV_TIME_STAMP_CONTROL_TIMER_DIV(preDiv);
    val |= BM_TIME_STAMP_CONTROL_TIMER_START;
    writel(val, base + TIME_STAMP_CONTROL_OFF);
}

/** *****************************************************************************************************
 * \brief Used to turn the CNTlock function.
 *
 * \verbatim
 * Syntax             : void Sent_Ip_TimeStampLatch(uint32_t base,
 *                          Sent_Ip_TimeStampOpType option)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - Sent base address
 *                      option - SENT_TIME_STAMP_LATCH_LOCK : latch lock
 *                               SENT_TIME_STAMP_LATCH_UNLOCK : latch unlock
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Used to turn the CNTlock function. A real CNT doesn't stop,
 *                      it just LOCKS the registers.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_TimeStampLatch(uint32_t base, Sent_Ip_TimeStampOpType option)
{
    uint32_t val = readl(base + TIME_STAMP_CONTROL_OFF);

    if (SENT_TIME_STAMP_LATCH_LOCK == option)
    {
        val |= BM_TIME_STAMP_CONTROL_TIMER_CNT_LATCH_MODE;
        val |= BM_TIME_STAMP_CONTROL_TIMER_CNT_LATCH_EN;
        writel(val, base + TIME_STAMP_CONTROL_OFF);
    }
    else
    {
        val &= (~BM_TIME_STAMP_CONTROL_TIMER_CNT_LATCH_MODE);
        val &= (~BM_TIME_STAMP_CONTROL_TIMER_CNT_LATCH_EN);
        writel(val, base + TIME_STAMP_CONTROL_OFF);
    }
}

/** *****************************************************************************************************
 * \brief clear time stamp cnt
 *
 * \verbatim
 * Syntax             : void Sent_Ip_TimeStampCntClr(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - Sent base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : clear time stamp cnt
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_TimeStampCntClr(uint32_t base)
{
    uint32_t val = readl(base + TIME_STAMP_CONTROL_OFF);
    val |= BM_TIME_STAMP_CONTROL_TIMER_RESET;
    writel(val, base + TIME_STAMP_CONTROL_OFF);
    val &= (~BM_TIME_STAMP_CONTROL_TIMER_RESET);
    writel(val, base + TIME_STAMP_CONTROL_OFF);
}

/** *****************************************************************************************************
 * \brief get time stamp counter
 *
 * \verbatim
 * Syntax             : void Sent_Ip_TimeStampGet(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - Sent base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : time stamp counter
 *
 * Return value       : None
 *
 * Description        : get time stamp counter
 * \endverbatim
 *******************************************************************************************************/
uint32_t Sent_Ip_TimeStampGet(uint32_t base)
{
    return readl(base + TIME_STAMP_COUNTER_OFF);
}

/** *****************************************************************************************************
 * \brief Check that the channels are configured properly and that
 *          certain functions are mutually exclusive.
 *
 * \verbatim
 * Syntax             : static lld_status_t Sent_Ip_ChannelCfgChk(
 *                                  const Sent_Ip_ChnCfgType *cfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : cfg - Sent config type
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId - SENT_E_CRC_CFG_FAILED or SENT_E_FRAME_CHK
 *
 * Description        : Check that the channels are configured properly and that
 *                      certain functions are mutually exclusive.
 * \endverbatim
 *******************************************************************************************************/
static lld_status_t Sent_Ip_ChannelCfgChk(const Sent_Ip_ChnCfgType *cfg)
{
    lld_status_t errorId = 0U;
    /* PRQA S 1881 23 */
    /** #10  */
    if ((true == (cfg->chnCfg.enhancedDataEn)) &&
            (false == (cfg->chnCfg.frameCrcDisable)) &&
            (NULL == (cfg->chnCfg.crc4Cfg)))
    {
        /* PRQA S 2855 1 */
        errorId = (lld_status_t)SENT_E_CRC_CFG_FAILED;
    } /* else not needed */

    if ((false == (cfg->chnCfg.enhancedDataEn)) &&
            ((false == (cfg->chnCfg.frameCrcDisable))) &&
            (NULL == (cfg->chnCfg.crc4Cfg)))
    {
        /* PRQA S 2855 1 */
        errorId = (lld_status_t)SENT_E_CRC_CFG_FAILED;
    } /* else not needed */

    if ((true == (cfg->chnCfg.pausePulseEn)) &&
            (SENT_SYNC_PULSE_OPTION2 == (cfg->chnCfg.calibSel)) &&
            (true == (cfg->chnCfg.frameLenChkEn)))
    {
        /* PRQA S 2855 1 */
        errorId = (lld_status_t)SENT_E_FRAME_CHK;
    } /* else not needed */

    return errorId;
}

/** *****************************************************************************************************
 * \brief div config
 *
 * \verbatim
 * Syntax             : static void Sent_Ip_ChannelDivCtrl(uint32_t base, Sent_Ip_ChannelType channel,
 *                                                         uint32_t tickCoun, uint32_t div)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      tickCoun - The counter of ticks
 *                      divider - The divider value
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : div config
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelDivCtrl(uint32_t base, Sent_Ip_ChannelType channel, uint32_t tickCoun, uint32_t divider)
{
    /* PRQA S 4521 3 */
    uint32_t regVal = FV_CHANNEL_PRE_DIVIDER_TICK_COUNTER(tickCoun) |
                      FV_CHANNEL_PRE_DIVIDER_FRACTIONAL_PRE_DIV(divider);
    /* PRQA S 3395,4521,4524 EOF */
    writel(regVal, (base + (CHANNEL_PRE_DIVIDER_OFF(channel))));
}

/** *****************************************************************************************************
 * \brief Configure the CRC configuration.
 *
 * \verbatim
 * Syntax             : static uint32_t Sent_Ip_ChannelCrcCfg
 *                          (const Sent_Ip_ChnCfgType *cfg, uint32_t regVal)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : cfg - Sent config type
 *                      regVal - The final register value of
 *                                  the CRC is calculated from this value.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Reduce register reads and writes, here only return the
 *                          value of the register will be at the end of the
 *
 * Description        : Configure the CRC configuration.
 * \endverbatim
 *******************************************************************************************************/
static uint32_t Sent_Ip_ChannelCrcCfg(const Sent_Ip_ChnCfgType *cfg, uint32_t regVal)
{
    uint32_t val = regVal;
    /* PRQA S 1881 51 */
    /** #10 config nibble data crc */
    if (false == cfg->chnCfg.frameCrcDisable)
    {
        val |= BM_CHANNEL_CTRL_NIBBBLE_CRC_EN;

        if (SENT_XOR_FIRST == cfg->chnCfg.crc4Cfg->chanCrcMode)
        {
            val |= BM_CHANNEL_CTRL_CRC4_ACE;
        } /* else not needed */

        if (true == cfg->chnCfg.crc4Cfg->statusNibCrc)
        {
            val |= BM_CHANNEL_CTRL_STATUS_NIB_CRC;
        } /* else not needed */

        if (SENT_SAE_J2716_2008 == cfg->chnCfg.crc4Cfg->nibbleDataCrc4)
        {
            val |= BM_CHANNEL_CTRL_CRC4_MODE;
        } /* else not needed */
    } /* else not needed */

    /** #20 config serial data crc */
    if ((false == cfg->chnCfg.serialCrcDisable) &&
            (false == cfg->chnCfg.enhancedDataEn))
    {
        val |= BM_CHANNEL_CTRL_SER_CRC_EN;

        if (SENT_XOR_FIRST == cfg->chnCfg.crc4Cfg->chanCrcMode)
        {
            val |= BM_CHANNEL_CTRL_CRC4_ACE;
        } /* else not needed */

        if (true == cfg->chnCfg.crc4Cfg->statusNibCrc)
        {
            val |= BM_CHANNEL_CTRL_STATUS_NIB_CRC;
        } /* else not needed */

        if (SENT_SAE_J2716_2008 == cfg->chnCfg.crc4Cfg->serDataCrc4)
        {
            val |= BM_CHANNEL_CTRL_CRC4_SER_MODE;
        } /* else not needed */
    } /* else not needed */

    /** #30 config serial enhanced data crc */
    if ((false == cfg->chnCfg.serialCrcDisable) &&
            (true == cfg->chnCfg.enhancedDataEn))
    {
        val |= BM_CHANNEL_CTRL_SER_CRC_EN;
    } /* else not needed */

    return val;
}

/** *****************************************************************************************************
 * \brief Calculate the value of the WDT register
 *
 * \verbatim
 * Syntax             : static uint32_t Sent_Ip_ChannelWdtCtrl(uint32_t wdtLen)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : wdtLen - The length of the WDT window.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Reduce register reads and writes, here only return the
 *                          value of the register will be at the end of the
 *
 * Description        : Calculate the value of the WDT register
 * \endverbatim
 *******************************************************************************************************/
static uint32_t Sent_Ip_ChannelWdtCtrl(uint32_t wdtLen)
{
    uint32_t val = 0U;

    if (0UL != wdtLen)
    {
        val |= BM_CHANNEL_CTRL_WDT_EN;
        val |= FV_CHANNEL_CTRL_CHN_WDT_LEN(wdtLen);
        val |= BM_CHANNEL_CTRL_IDLE_TIMEOUT;
    } /* else not needed */

    return val;
}

/** *****************************************************************************************************
 * \brief Configure the filtering parameters.
 *
 * \verbatim
 * Syntax             : static void Sent_Ip_ChannelFilterCtrl(uint32_t base, Sent_Ip_ChannelType channel
 *                                                            const Sent_Ip_ChnCfgType *cfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      cfg - Sent config type
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure the filtering parameters.
 * \endverbatim
 *******************************************************************************************************/
static void Sent_Ip_ChannelFilterCtrl(uint32_t base, Sent_Ip_ChannelType channel, const Sent_Ip_ChnCfgType *cfg)
{
    uint32_t regVal = 0UL;
    /* PRQA S 1881 13 */
    if (true == cfg->chnCfg.invertInputSigEn)
    {
        regVal |= BM_INPUT_FILTER_CTRL_CHN_IN_INV;
    } /* else not needed */

    if (true == cfg->chnCfg.chnFirstGlitchIgnore)
    {
        regVal |= BM_INPUT_FILTER_CTRL_CHN_IGNORE_INI_GLITCH;
    } /* else not needed */

    regVal |= FV_INPUT_FILTER_CTRL_CHN_F_DEPTH(cfg->chnCfg.chnGlitchFall);
    regVal |= FV_INPUT_FILTER_CTRL_CHN_R_DEPTH(cfg->chnCfg.chnGlitchRis);
    /* PRQA S 4521 1 */
    writel(regVal, ((base) +  (INPUT_FILTER_CTRL_OFF(channel))));
}

/** *****************************************************************************************************
 * \brief Configure the DMA mode function.
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelDmaCtrl(uint32_t base, Sent_Ip_ChannelType channel,
 *                                                  bool dmaNibEn, bool dmaSerEn)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      dmaNibEn - true:Enable nibble_DMA for the channel.
 *                                 false:Disables nibble_DMA for the channel.
 *                      dmaSerEn - true:Enable serial_DMA the channel.
 *                                 false:Disables serial_DMA for the channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure the DMA mode function.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelDmaCtrl(uint32_t base, Sent_Ip_ChannelType channel, bool dmaNibEn, bool dmaSerEn)
{
    uint32_t regVal = readl(base + DMA_CTRL_OFF);
    /* PRQA S 1881 EOF */
    if (true == (dmaNibEn | dmaSerEn))
    {
        if (BM_DMA_CTRL_DMA_FIFO_SRST == (regVal & BM_DMA_CTRL_DMA_FIFO_SRST))
        {
            regVal &= (~BM_DMA_CTRL_DMA_FIFO_SRST);
        } /* else not needed */

        regVal |= BM_DMA_CTRL_DMA_START;

        if (true == dmaNibEn)
        {
            /* PRQA S 4524 1 */
            regVal |= FV_DMA_CTRL_CHN_DMA_NIB_EN_MASK(0x01UL << channel);
        } /* else not needed */

        if (true == dmaSerEn)
        {
            /* PRQA S 4524 1 */
            regVal |= FV_DMA_CTRL_CHN_DMA_SER_EN_MASK(0x01UL << channel);
        } /* else not needed */

        writel(regVal, base + DMA_CTRL_OFF);
    }
    else
    {
        /* PRQA S 4524 2 */
        regVal &= (~FV_DMA_CTRL_CHN_DMA_NIB_EN_MASK(0x01UL << channel));
        regVal &= (~FV_DMA_CTRL_CHN_DMA_SER_EN_MASK(0x01UL << channel));
        writel(regVal, base + DMA_CTRL_OFF);
    }

}

/* PRQA S 1505 EOF */
/** *****************************************************************************************************
 * \brief Configure SENT channel-related configuration.
 *
 * \verbatim
 * Syntax             : lld_status_t Sent_Ip_ChannelCtrl(uint32_t base, Sent_Ip_ChannelType channel,
 *                                                       const Sent_Ip_ChnCfgType *cfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      cfg - Sent config type
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorID - SENT_E_CRC_CFG_FAILED or SENT_E_FRAME_CHK
 *
 * Description        : Configure SENT channel-related configuration.
 * \endverbatim
 *******************************************************************************************************/
lld_status_t Sent_Ip_ChannelCtrl(uint32_t base, Sent_Ip_ChannelType channel,
                                 const Sent_Ip_ChnCfgType *cfg)
{
    lld_status_t errorId = Sent_Ip_ChannelCfgChk(cfg);
    uint32_t regVal;

    if (0U == errorId)
    {
        /** #10  Configure CHANNEL_CTRLn for SENT channel all control options. */
        Sent_Ip_ChannelDivCtrl(base, channel, cfg->chnCfg.tickCoun, cfg->chnCfg.div);
        regVal = Sent_Ip_ChannelWdtCtrl(cfg->chnCfg.wdtLen);

        if (true == cfg->chnCfg.ignoreFirSer)
        {
            regVal |= BM_CHANNEL_CTRL_SER_FIRST_IGNORE;
        } /* else not needed */

        regVal = Sent_Ip_ChannelCrcCfg(cfg, regVal);

        if (SENT_CAL_PULSE_20 == cfg->chnCfg.calibPulse)
        {
            regVal |= BM_CHANNEL_CTRL_CALIB_PULSE_VAR;
        } /* else not needed */

        if (SENT_SYNC_PULSE_OPTION2 == cfg->chnCfg.calibSel)
        {
            regVal |= BM_CHANNEL_CTRL_PULSE_DET_MODE;
        } /* else not needed */

        if (true == cfg->chnCfg.FirstCalPulseChk)
        {
            regVal |= BM_CHANNEL_CTRL_INI_PULSE_SUSCCHK;
        } /* else not needed */

        writel(regVal, base +  CHANNEL_CTRL_OFF(channel));

        /** #20 cfg CHN_FRAME_CTRL */
        regVal = 0UL;
        regVal |= BM_CHN_FRAME_CTRL_FRAME_INVA_IGNORE;

        if (true == cfg->chnCfg.enhancedDataEn)
        {
            regVal |= BM_CHN_FRAME_CTRL_SER_ENH_EN;
        } /* else not needed */

        if (true == cfg->chnCfg.frameLenChkEn)
        {
            regVal |= BM_CHN_FRAME_CTRL_FRAME_LEN_CHK;
        } /* else not needed */

        if (true == cfg->chnCfg.pausePulseEn)
        {
            regVal |= BM_CHN_FRAME_CTRL_CHN_PAUSE;
        } /* else not needed */

        regVal |= FV_CHN_FRAME_CTRL_CHN_FRAME_NIB(cfg->chnCfg.nibbleNum - 1UL);
        writel(regVal, base +  CHN_FRAME_CTRL_OFF(channel));

        /** #30 config data view */
        writel(cfg->chnCfg.dataView & (~CHN_FRAME_NIB_P_RESERVED),
               base +  CHN_FRAME_NIB_P_OFF(channel));

        /** #40 config glitch */
        Sent_Ip_ChannelFilterCtrl(base, channel, cfg);
    }

    return errorId;
}

/** *****************************************************************************************************
 * \brief Configure SENT enable operation.
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelEnable(uint32_t base, Sent_Ip_ChannelType channel, bool enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      enable - true:Enables SENT channel reception.
 *                               false:Disables the SENT channel receive function.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure SENT enable operation.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelEnable(uint32_t base, Sent_Ip_ChannelType channel, bool enable)
{
    uint32_t regVal = readl(base + CHANNEL_RESET_OFF);

    if (true == enable)
    {
        regVal |= FV_CHANNEL_RESET_CHANNEL_EN(0x01UL << channel);
        writel(regVal, base + CHANNEL_RESET_OFF);
    }
    else
    {
        regVal &= (~FV_CHANNEL_RESET_CHANNEL_EN(0x01UL << channel));
        writel(regVal, base + CHANNEL_RESET_OFF);
    }
}

/** *****************************************************************************************************
 * \brief Configure SENT clock enable operation.
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelClkEnable(uint32_t base, Sent_Ip_ChannelType channel,
 *                                                    bool enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      enable - true:Enables clock SENT channel reception.
 *                               false:Disables clock the SENT channel receive function.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure SENT clock enable operation.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelClkEnable(uint32_t base, Sent_Ip_ChannelType channel, bool enable)
{
    uint32_t regVal = readl(base + CHANNEL_RESET_OFF);

    if (true == enable)
    {
        regVal |= FV_CHANNEL_RESET_CHANNEL_CLK_EN(0x01UL << channel);
        writel(regVal, base + CHANNEL_RESET_OFF);
    }
    else
    {
        regVal &= (~FV_CHANNEL_RESET_CHANNEL_CLK_EN(0x01UL << channel));
        writel(regVal, base + CHANNEL_RESET_OFF);
    }
}

/** *****************************************************************************************************
 * \brief Configure SENT channel release config
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelRelease(uint32_t base, Sent_Ip_ChannelType channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Configure SENT channel release config.
 *                      Does not affect registers, affects digital logic including FIFO clearing.
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelRelease(uint32_t base, Sent_Ip_ChannelType channel)
{
    uint32_t regVal = readl(base + CHANNEL_RESET_OFF);
    uint32_t tms = 0UL;

    regVal |= FV_CHANNEL_RESET_CHANNEL_SW_RST(0x01UL << channel);
    writel(regVal, base + CHANNEL_RESET_OFF);
    regVal = readl(base + CHANNEL_RESET_OFF);
    /** #10 Wait CHANNEL_RESET.CHANNELn_SW_RST bit to self
     * cleared for exit soft reset state.delay 90us */
    while (((regVal & FV_CHANNEL_RESET_CHANNEL_SW_RST(0x01UL << channel)) > 0UL) &&
            (tms <= SENT_POLLING_RST_TMS))
    {
        regVal = readl(base + CHANNEL_RESET_OFF);
        tms++;
    }
}

/** *****************************************************************************************************
 * \brief SENT Interrupt Initialization Configuration
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelInterruptEnable(uint32_t base, Sent_Ip_ChannelType channel,
 *                                                          uint32_t interruptMsk)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      interruptMsk - The combination of Sent_Ip_ChannelStaType
 *                                      in the enumeration type.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : SENT Interrupt Initialization Configuration
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelInterruptEnable(uint32_t base, Sent_Ip_ChannelType channel, uint32_t interruptMsk)
{
    writel(interruptMsk, base + CHANNEL_STA_EN_OFF(channel));
    writel(interruptMsk, base + CHANNEL_SIG_EN_OFF(channel));
}

/** *****************************************************************************************************
 * \brief Get the channel status
 *
 * \verbatim
 * Syntax             : uint32_t Sent_Ip_ChannelStaGet(uint32_t base,
 *                                      Sent_Ip_ChannelType channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : channel status
 *
 * Description        : Get the channel status
 * \endverbatim
 *******************************************************************************************************/
uint32_t Sent_Ip_ChannelStaGet(uint32_t base, Sent_Ip_ChannelType channel)
{
    return readl(base + CHANNEL_STATUS_OFF(channel)) & CHANNEL_STATUS_VALID_BIT;
}

/** *****************************************************************************************************
 * \brief Get the channel irq status
 *
 * \verbatim
 * Syntax             : uint32_t Sent_Ip_ChannelIrqStaGet(uint32_t base,
 *                                      Sent_Ip_ChannelType channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : channel irq status
 *
 * Description        : Get the channel irq status
 * \endverbatim
 *******************************************************************************************************/
uint32_t Sent_Ip_ChannelIrqStaGet(uint32_t base, Sent_Ip_ChannelType channel)
{
    return readl(base + CHANNEL_STA_OFF(channel)) & CHANNEL_STA_VALID_BIT;
}

/** *****************************************************************************************************
 * \brief Clear interrupt status
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ChannelStaClr(uint32_t base,
 *                          Sent_Ip_ChannelType channel, uint32_t bitMsk)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *                      bitMsk - Interrupt bit
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Clear interrupt status
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ChannelStaClr(uint32_t base, Sent_Ip_ChannelType channel, uint32_t bitMsk)
{
    writel(bitMsk, base + CHANNEL_STA_OFF(channel));
}

/** *****************************************************************************************************
 * \brief Processing of nibble data
 *
 * \verbatim
 * Syntax             : void Sent_Ip_NibDataProcess(uint32_t nibFrame1,
 *                              uint32_t nibFrame2, uint32_t timeStamp,
 *                              Sent_Ip_NibDataType *nibData)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : reentrant
 *
 * Parameters (in)    : nibFrame1 - fifo1 data
 *                      nibFrame2 - fifo2 data
 *                      timeStamp - fifo time stamp
 *
 * Parameters (inout) : nibData - nibble The structure of the data returned.
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Processing of nibble data
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_NibDataProcess(uint32_t nibFrame1, uint32_t nibFrame2, uint32_t timeStamp,
                                   Sent_Ip_NibDataType *nibData)
{
    /* PRQA S 4442,4394,4342,4464,4461 EOF */
    nibData->channelId = (Sent_Ip_ChannelType)GFV_CHN_FRAME1_CHN_NUM(nibFrame1);
    nibData->frameType = (Sent_Ip_FrameType)GFV_CHN_FRAME1_F(nibFrame1);
    nibData->validData = (bool)GFV_CHN_FRAME1_V(nibFrame1);
    nibData->SCN = GFV_CHN_NIB_FRAME1_SCN(nibFrame1);
    nibData->crc = GFV_CHN_NIB_FRAME1_CRC(nibFrame1);
    nibData->nibbleData = nibFrame2;
    nibData->timeStamp = timeStamp;
}

/** *****************************************************************************************************
 * \brief Get nibble data
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ReadNibData(uint32_t base,
 *                          Sent_Ip_ChannelType channel, Sent_Ip_NibDataType *nibData)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *
 * Parameters (inout) : nibData - nibble The structure of the data returned.
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Get nibble data
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ReadNibData(uint32_t base, Sent_Ip_ChannelType channel, Sent_Ip_NibDataType *nibData)
{
    uint32_t nibFrame1 = readl(base + CHN_NIB_FRAME1_OFF(channel));
    uint32_t nibFrame2 = readl(base + CHN_NIB_FRAME2_OFF(channel));
    uint32_t timeStamp = readl(base + CHN_NIB_STAMP_OFF(channel));
    Sent_Ip_NibDataProcess(nibFrame1, nibFrame2, timeStamp, nibData);
}

/** *****************************************************************************************************
 * \brief Processing of serial data
 *
 * \verbatim
 * Syntax             : void Sent_Ip_SerDataProcess(uint32_t serFrame1,
 *                              uint32_t serFrame2, uint32_t timeStamp,
 *                              Sent_Ip_SerDataType *serData)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : reentrant
 *
 * Parameters (in)    : serFrame1 - fifo1 data
 *                      serFrame2 - fifo2 data
 *                      timeStamp - fifo time stamp
 *
 * Parameters (inout) : serData - serial The structure of the data returned.
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Processing of serial data
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_SerDataProcess(uint32_t serFrame1, uint32_t serFrame2, uint32_t timeStamp,
                                   Sent_Ip_SerDataType *serData)
{
    serData->channelId = (Sent_Ip_ChannelType)GFV_CHN_FRAME1_CHN_NUM(serFrame1);
    serData->frameType = (Sent_Ip_FrameType)GFV_CHN_FRAME1_F(serFrame1);
    serData->validData = (bool)GFV_CHN_FRAME1_V(serFrame1);
    serData->Configuration = GFV_CHN_SER_FRAME2_C(serFrame2);
    serData->serMessType = GFV_CHN_SER_FRAME2_T(serFrame2);
    serData->crc = GFV_CHN_SER_FRAME2_CRC(serFrame2);
    serData->msgId = GFV_CHN_SER_FRAME2_MID(serFrame2);
    serData->data = GFV_CHN_SER_FRAME2_DATA(serFrame2);
    serData->timeStamp = timeStamp;
}

/** *****************************************************************************************************
 * \brief Get serial data
 *
 * \verbatim
 * Syntax             : void Sent_Ip_ReadSerData(uint32_t base,
 *                              Sent_Ip_ChannelType channel, Sent_Ip_SerDataType *serData)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - Channel ID
 *
 * Parameters (inout) : serData - serial The structure of the data returned.
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Get serial data
 * \endverbatim
 *******************************************************************************************************/
void Sent_Ip_ReadSerData(uint32_t base, Sent_Ip_ChannelType channel, Sent_Ip_SerDataType *serData)
{
    uint32_t serFrame1 = readl(base + CHN_SER_FRAME1_OFF(channel));
    uint32_t serFrame2 = readl(base + CHN_SER_FRAME2_OFF(channel));
    uint32_t timeStamp = readl(base + CHN_SER_STAMP_OFF(channel));
    Sent_Ip_SerDataProcess(serFrame1, serFrame2, timeStamp, serData);
}

/** *****************************************************************************************************
 * \brief Get channel interrupt status
 *
 * \verbatim
 * Syntax             : uint32_t Sent_Ip_GetChannelIntSta(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - SENT base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Get channel interrupt status
 * \endverbatim
 *******************************************************************************************************/
uint32_t Sent_Ip_GetChannelIntSta(uint32_t base)
{
    return GFV_REVISION_INTR_STAT(readl(base + REVISION_OFF));
}

/** *****************************************************************************************************
 * \brief Actual Calculation Result of Tick Period
 *
 * \verbatim
 * Syntax             : uint32_t Sent_Ip_GetChannelActualTick(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - SENT base address
 *                      channel - channelId
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : actual tick
 *
 * Description        : Actual Calculation Result of Tick Period
 * \endverbatim
 *******************************************************************************************************/
uint32_t Sent_Ip_GetChannelActualTick(uint32_t base, Sent_Ip_ChannelType channel)
{
    return GFV_CHANNEL_TICK_RESULT_TICK_RESULT(readl(base + CHANNEL_TICK_RESULT_OFF(channel)));
}

#ifdef CFG_PLATFORM_MCAL
#define SENT_STOP_SEC_CODE
#include "Sent_MemMap.h"
#elif CFG_PLATFORM_SSDK
#else
#error "Undefined macros CFG_PLATFORM_MCAL or CFG_PLATFORM_SSDK"
#endif /** #ifdef CFG_PLATFORM_MCAL */

/* End of file */
